package com.fourth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fourth.conf.BusinessException;
import com.fourth.constant.CommonErrorCode;
import com.fourth.dto.*;
import com.fourth.entity.DatabaseManage;
import com.fourth.mapper.DatabaseManageMapper;
import com.fourth.service.DatabaseManageService;
import com.fourth.utils.BizAssertUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据源信息表 服务实现类
 * </p>
 *
 * @author cfy
 * @since 2023-02-27
 */
@Slf4j
@Service
public class DatabaseManageServiceImpl extends ServiceImpl<DatabaseManageMapper, DatabaseManage> implements DatabaseManageService {

    /**
     * 添加或修改数据源
     *
     * @param addOrUpdateDatabaseDto
     * @return
     */
    @Override
    public boolean addOrUpdate(AddOrUpdateDatabaseDto addOrUpdateDatabaseDto) {

        // 数据库类型默认Mysql，不能变
        BizAssertUtils.isTrue(addOrUpdateDatabaseDto.getType().equals("Mysql"),
                "数据库类型默认Mysql，不能变");

        // 查询条件
        LambdaQueryWrapper<DatabaseManage> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1
                .ne(addOrUpdateDatabaseDto.getId() != null,
                        DatabaseManage::getId, addOrUpdateDatabaseDto.getId())
                // 未被删除的
                .eq(DatabaseManage::getRemoveStatus, 0)
                .and(a -> {
                    a.eq(DatabaseManage::getName, addOrUpdateDatabaseDto.getName())
                            .or()
                            .eq(DatabaseManage::getJdbcUrl, addOrUpdateDatabaseDto.getJdbcUrl());
                })
                .last("limit 1")
        ;

        // 查询是否有数据源名称和url相同的数据
        DatabaseManage databaseManageAnother = getOne(lambdaQueryWrapper1);

        // 如果存在相同数据
        if (databaseManageAnother != null) {
            // 数据源名称相同
            BizAssertUtils.isFalse(databaseManageAnother.getName().equals(addOrUpdateDatabaseDto.getName()),
                    "该数据源名称已存在");
            // url相同
            BizAssertUtils.isFalse(databaseManageAnother.getJdbcUrl().equals(addOrUpdateDatabaseDto.getJdbcUrl()),
                    "该数据源jdbc_url已存在");
        }

        // 修改方向
        if (addOrUpdateDatabaseDto.getId() != null) {
            LambdaQueryWrapper<DatabaseManage> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
            lambdaQueryWrapper2
                    .eq(DatabaseManage::getId, addOrUpdateDatabaseDto.getId())
            ;
            // 查询该数据源是否存在
            DatabaseManage databaseManagePre = getOne(lambdaQueryWrapper2);
            BizAssertUtils.isTrue(databaseManagePre != null, "该数据源不存在");
            // 是否已被删除
            assert databaseManagePre != null;
            BizAssertUtils.isFalse(databaseManagePre.getRemoveStatus(), "该数据源已被删除，不能进行修改");
            // 状态是否为发布状态
            BizAssertUtils.isTrue(databaseManagePre.getApplyStatus() != 1 ,
                    "该数据源为发布状态，不能进行修改");
        }

        // 创建数据源实例
        DatabaseManage databaseManage = new DatabaseManage();

        // 拷贝bean
        BeanUtils.copyProperties(addOrUpdateDatabaseDto, databaseManage);

        return this.saveOrUpdate(databaseManage);
    }

    @Override
    public Page<QueryListDto> queryDatabase(QueryDatabaseDto queryDatabaseDto) {
        Page<DatabaseManage> page = new Page<>();
        page.setCurrent(queryDatabaseDto.getCurrent());
        page.setSize(queryDatabaseDto.getPageSize());

        Boolean removeStatusFalse = false;
        LambdaQueryWrapper<DatabaseManage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .like(!StringUtils.isBlank(queryDatabaseDto.getName()), DatabaseManage::getName, queryDatabaseDto.getName())
                .eq(queryDatabaseDto.getApplyStatus() != null, DatabaseManage::getApplyStatus, queryDatabaseDto.getApplyStatus())
                .eq(DatabaseManage::getRemoveStatus, removeStatusFalse)
                .orderByDesc(DatabaseManage::getApplyStatus)
                .orderByAsc(queryDatabaseDto.getSort()==1,DatabaseManage::getUpdateTime)
                .orderByDesc(queryDatabaseDto.getSort()==0,DatabaseManage::getUpdateTime)
        ;
        Page<DatabaseManage> databaseManagePage = page(page, lambdaQueryWrapper);
        //返回我们所需要的对象列表
        List<QueryListDto> queryListDto = databaseManagePage.getRecords().stream()
                .map(item -> {
                    //进行重新组装新对象
                    QueryListDto queryDto = new QueryListDto();
                    queryDto.setId(item.getId());
                    queryDto.setName(item.getName());
                    queryDto.setDescription(item.getDescription());
                    queryDto.setDriverClass(item.getDriverClass());
                    queryDto.setApplyStatus(item.getApplyStatus());
                    queryDto.setJdbcUrl(item.getJdbcUrl());
                    queryDto.setUpdateTime(item.getUpdateTime());
                    return queryDto;
                })
                .collect(Collectors.toList());
        Page<QueryListDto> queryListDtoPage = new Page<>();
        queryListDtoPage.setRecords(queryListDto);
        queryListDtoPage.setTotal(databaseManagePage.getTotal());

        return queryListDtoPage;
    }

    @Override
    public DatabaseDto getDatabaseById(Integer id) {
        BizAssertUtils.notNull(id,"id不能为空");
        DatabaseManage byId = getById(id);
        BizAssertUtils.notNull(byId,"该数据源不存在");
        DatabaseDto databaseDto = new DatabaseDto();
        BeanUtils.copyProperties(byId,databaseDto);
        return databaseDto;
    }

    /**
     * 删除数据源
     *
     * @param deleteDto
     * @return
     */
    @Override
    public Integer delete(@NotNull DeleteDto deleteDto) {
        Integer flag = 0;
        LambdaQueryWrapper<DatabaseManage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DatabaseManage::getId, deleteDto.getId());
        DatabaseManage databaseManage = getOne(lambdaQueryWrapper);
        System.out.println("databaseManage:" + databaseManage);
        BizAssertUtils.isFalse(databaseManage == null, "删除失败，该用户不存在");
        BizAssertUtils.isFalse(databaseManage.getApplyStatus().equals(1), "已发布,不能删除");
        BizAssertUtils.isFalse(databaseManage.getApplyStatus().equals(0), "已禁用,不能删除");
        BizAssertUtils.isFalse(databaseManage.getRemoveStatus() == true, "数据源已删除");
        if (databaseManage != null) {
            DatabaseManage databaseManage1 = new DatabaseManage();
            databaseManage1.setRemoveStatus(true);
            update(databaseManage1, lambdaQueryWrapper);
            flag = 1;
        }
        return flag;
    }

    /**
     * 修改数据源
     *
     * @param changeApplyStatusDto
     * @return
     */
    @Override
    public Integer changeApplyStatus(ChangeApplyStatusDto changeApplyStatusDto) {
        Integer flag = 0;
        LambdaQueryWrapper<DatabaseManage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DatabaseManage::getId, changeApplyStatusDto.getId());
        DatabaseManage databaseManageOne = getOne(lambdaQueryWrapper);
        BizAssertUtils.isFalse(databaseManageOne == null, "修改失败，该用户不存在");
        BizAssertUtils.isFalse(!changeApplyStatusDto.getApplyStatus().equals(databaseManageOne.getApplyStatus()), "传入状态与实际状态不符");

        DatabaseManage databaseManage = new DatabaseManage();

        //默认状态(未发布),修改只能转为已发布
        if (databaseManageOne.getApplyStatus().equals(2)) {
            databaseManage.setApplyStatus(1);
        } else if (databaseManageOne.getApplyStatus() == 1 || databaseManageOne.getApplyStatus() == 0) {
            databaseManage.setApplyStatus(databaseManageOne.getApplyStatus() == 1 ? 0 : 1);
        }
        if (this.update(databaseManage, lambdaQueryWrapper)) {
            flag = 1;
        }
        return flag;
    }

    @Override
    public void connectionDataSource(TestConnectionDto testConnectionDto) {
        if(testConnectionDto.getType().equals("Mysql")){
            String url = testConnectionDto.getJdbcUrl();
            String username = testConnectionDto.getUserName();
            String password = testConnectionDto.getPassword();
            try {
                Class.forName(testConnectionDto.getDriverClass());
                Connection con = DriverManager.getConnection(url, username, password);
                con.close();
            } catch (ClassNotFoundException | LinkageError er) {
                //抛出异常
                log.error("连通测试失败,驱动错误："+ er.getMessage());
                BusinessException.throwIt("连通测试失败,驱动错误", CommonErrorCode.DB_ERROR.getCode());
            }catch (SQLException sq){
                log.error("连通测试失败,连接异常："+ sq.getMessage());
                BusinessException.throwIt("连通测试失败,连接异常，请检查url、用户名或密码" , CommonErrorCode.DB_ERROR.getCode());
            }catch (Exception e){
                log.error("连通测试失败,未知错误："+ e.getMessage());
                BusinessException.throwIt("连通测试失败,未知错误，请联系管理员" , CommonErrorCode.DB_ERROR.getCode());
            }
        }else{
            BusinessException.throwIt("连通测试失败，类型不正确", CommonErrorCode.BUSINESS_ERROR.getCode());
        }
    }


}
